package main

import (
	"errors"
	"math"
	"time"
	"github.com/open-falcon/rrdlite"
    //"github.com/yubo/rrdlite"
	"github.com/toolkits/file"
    "fmt"
)

type TimeValue struct {
    Timestamp   int64      `json:"timestamp"`
    Value       float64    `json:"value"`
}


const (
	RRA1PointCnt   = 720 // 1m一个点存12h
	RRA5PointCnt   = 576 // 5m一个点存2d
	RRA20PointCnt  = 504 // 20m一个点存7d
	RRA180PointCnt = 766 // 3h一个点存3month
	RRA720PointCnt = 730 // 12h一个点存1year
)

func create(filename string, item *TimeValue) error {
	now := time.Now()
	start := now.Add(time.Duration(-24) * time.Hour)

	c := rrdlite.NewCreator(filename, start, 60)
	// 从filename里解析出Dstype和step
	// f529ed1a3fd589d543d5f79ecb9c0b9c_GAUGE_60
	c.DS("metric", "GAUGE", 120, "0", "U")

	// 设置各种归档策略
	// 1分钟一个点存 12小时
	c.RRA("AVERAGE", 0, 1, RRA1PointCnt)

	// 5m一个点存2d
	c.RRA("AVERAGE", 0, 5, RRA5PointCnt)
	c.RRA("MAX", 0, 5, RRA5PointCnt)
	c.RRA("MIN", 0, 5, RRA5PointCnt)

	// 20m一个点存7d
	c.RRA("AVERAGE", 0, 20, RRA20PointCnt)
	c.RRA("MAX", 0, 20, RRA20PointCnt)
	c.RRA("MIN", 0, 20, RRA20PointCnt)

	// 3小时一个点存3个月
	c.RRA("AVERAGE", 0, 180, RRA180PointCnt)
	c.RRA("MAX", 0, 180, RRA180PointCnt)
	c.RRA("MIN", 0, 180, RRA180PointCnt)

	// 12小时一个点存1year
	c.RRA("AVERAGE", 0, 720, RRA720PointCnt)
	c.RRA("MAX", 0, 720, RRA720PointCnt)
	c.RRA("MIN", 0, 720, RRA720PointCnt)

	return c.Create(true)
}

func flushrrd(filename string, items []*TimeValue) error {
	if items == nil || len(items) == 0 {
		return errors.New("empty items")
	}
    if !file.IsExist(filename) {
        fmt.Println(111111)
		baseDir := file.Dir(filename)

		err := file.InsureDir(baseDir)
		if err != nil {
            fmt.Println(22222)
			return err
		}

		err = create(filename, items[0])
		if err != nil {
            fmt.Println(33333, err)
			return err
		}
    }
	return update(filename, items)
}

func update(filename string, items []*TimeValue) error {

	u := rrdlite.NewUpdater(filename)

	for _, item := range items {
		v := math.Abs(item.Value)
		if v > 1e+300 || (v < 1e-300 && v > 0) {
			continue
		}
		u.Cache(item.Timestamp, int(item.Value))
	}

	return u.Update()
}

func alignTs(ts int64, period int64) int64 {
    return ts - ts%period
}

func main(){
        fname := "2.rrd"
        var value float64 = 10
        for {

    		ts := time.Now().Unix()
            ts = alignTs(ts, 60)
	    	item := &TimeValue{
		    	Timestamp: ts,
		    	Value: value,
    		}
	       flushrrd(fname, []*TimeValue{
				item, 
    	  })
          fmt.Println(ts, value)
          time.Sleep(60*time.Second)
          value ++
       }
}
